package com.sz.biz.logistics.bill.service.impl;

import com.sz.biz.common.AbstractVersionEntityService;
import com.sz.biz.common.customer.entity.CusUser;
import com.sz.biz.common.customer.service.CustomerUserService;
import com.sz.biz.logistics.bill.dto.BillingOrderFeeDto;
import com.sz.biz.logistics.bill.dto.BillingOrderListDto;
import com.sz.biz.logistics.bill.dto.BillingOrderListStringDto;
import com.sz.biz.logistics.bill.entity.BillingOrderRel;
import com.sz.biz.logistics.bill.entity.BillingTask;
import com.sz.biz.logistics.bill.service.BillingOrderRelService;
import com.sz.biz.logistics.bill.service.BillingService;
import com.sz.biz.logistics.bill.service.BillingTaskService;
import com.sz.biz.logistics.ord.service.OrdServiceBillService;
import com.sz.biz.trade.constants.TrdConstants;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.utils.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Function: 账单订单管理<br>
 * Author: jifeixing <br>
 * Date: 2017-05-19 15:10:00
 */
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public class BillingOrderRelServiceImpl extends AbstractVersionEntityService implements BillingOrderRelService {

    private static final String TYPE = "type";
    @Autowired
    private OrdServiceBillService ordServiceBillService;
    @Autowired
    private BillingService billingService;
    @Autowired
    private CustomerUserService customerUserService;
    @Autowired
    private BillingTaskService billingTaskService;

    /**
     * 保存账单关联关系
     *
     * @param billingOrderRel
     */
    @Override
    public void save(BillingOrderRel billingOrderRel) {
        dao.save(getSqlName("insertSelective"), billingOrderRel);
    }

    /**
     * 根据账单号获取下属所有订单号
     * @param billNos
     * @return
     */
    @Override
    public List<String> findOrderNosByBillNo(List<String> billNos,String type){
        ParamData paramData = new ParamData();
        paramData.put("billNos", billNos);
        paramData.put("type", type);
        return dao.findForList(getSqlName("findOrderNosByBillNo"), paramData, String.class);
    }

    /**
     * 根据账单号获取账单下所有订单
     * @param billNo
     * @return
     */
    @Override
    public List<BillingOrderListStringDto> findOrdersByBillNo(String billNo,String type){
        ParamData paramData = new ParamData();
        paramData.put("billNo", billNo);
        paramData.put("type", type);
        //根据条件获取账单列表
        return ordersByBillNo(paramData, "findOrdersByBillNo");
    }

    /**
     * 账单下所有订单
     * @param pd
     * @return
     */
    private List<BillingOrderListStringDto> ordersByBillNo(ParamData pd, String sqlName){
        List<BillingOrderListStringDto> billingListString = new ArrayList<>();
        //根据条件获取账单列表
        List<BillingOrderListDto> billingList = dao.findForList(getSqlName(sqlName), pd, BillingOrderListDto.class);
        //订单金额
        List<BillingOrderFeeDto> orderFeeList = getOrderFee(billingList,pd.getString(TYPE));
        if(TrdConstants.BillType.RECEIVALE.equals(pd.getString(TYPE))){
            if(null != orderFeeList && null != billingList){
                for(BillingOrderListDto billing : billingList){
                    List<Map<String, Object>> feeList = new ArrayList<>();
                    BigDecimal orderTotalFee = BigDecimal.ZERO;
                    for(BillingOrderFeeDto billingOrder : orderFeeList){
                        if(billing.getOrderNo().equals(billingOrder.getOrderNo())&&billingOrder.getServiceName().equals(billing.getServiceName())){
                            orderTotalFee = orderTotalFee.add(billingOrder.getAmountDue());
                            Map<String, Object> map = new HashMap<>();
                            map.put(TYPE, billingOrder.getFeeTypeName());
                            map.put("supplierId",billing.getCustomerId());
                            BigDecimal orderFee = billingOrder.getAmountDue();
                            if(null != orderFee){
                                orderFee = orderFee.setScale(3, BigDecimal.ROUND_HALF_UP);
                            }
                            map.put("value", orderFee + "");
                            feeList.add(map);
                        }
                    }
                    //每个订单的总计金额
                    orderTotalFee = orderTotalFee.setScale(3, BigDecimal.ROUND_HALF_UP);
                    billing.setAmountDue(orderTotalFee);
                    //返回数据
                    billing.setOrderFeeList(feeList);
                    BillingOrderListStringDto billingOrderListStringDto = new BillingOrderListStringDto();
                    BeanUtils.copyProperties(billing, billingOrderListStringDto);
                    billingOrderListStringDto.setAmountDue(billing.getAmountDue().toString());
                    billingListString.add(billingOrderListStringDto);
                }
            }
        }else{
            if(null != orderFeeList && null != billingList){
                for(BillingOrderListDto billing : billingList){
                    List<Map<String, Object>> feeList = new ArrayList<>();
                    BigDecimal orderTotalFee = BigDecimal.ZERO;
                    for(BillingOrderFeeDto billingOrder : orderFeeList){
                        if(billing.getOrderNo().equals(billingOrder.getOrderNo())){
                            orderTotalFee = orderTotalFee.add(billingOrder.getAmountDue());
                            Map<String, Object> map = new HashMap<>();
                            map.put(TYPE, billingOrder.getFeeTypeName());
                            BigDecimal orderFee = billingOrder.getAmountDue();
                            if(null != orderFee){
                                orderFee = orderFee.setScale(3, BigDecimal.ROUND_HALF_UP);
                            }
                            map.put("value", orderFee + "");
                            feeList.add(map);
                        }
                    }
                    //每个订单的总计金额
                    orderTotalFee = orderTotalFee.setScale(3, BigDecimal.ROUND_HALF_UP);
                    billing.setAmountDue(orderTotalFee);
                    //返回数据
                    billing.setOrderFeeList(feeList);
                    BillingOrderListStringDto billingOrderListStringDto = new BillingOrderListStringDto();
                    BeanUtils.copyProperties(billing, billingOrderListStringDto);
                    billingOrderListStringDto.setAmountDue(billing.getAmountDue().toString());
                    billingListString.add(billingOrderListStringDto);
                }
            }
        }

        return billingListString;
    }


    /**
     * 账单下所有订单
     * @param pd
     * @return
     */
    @Override
    public List<BillingOrderListStringDto> ordersByBillNoAndSupplier(ParamData pd, String sqlName){
        List<BillingOrderListStringDto> billingListString = new ArrayList<>();
        //根据条件获取账单列表
        List<BillingOrderListDto> billingList = dao.findForList(getSqlName(sqlName), pd, BillingOrderListDto.class);
        //订单金额
        List<BillingOrderFeeDto> orderFeeList = getOrderFee(billingList,pd.getString(TYPE));
        if(null != orderFeeList && null != billingList){
            for(BillingOrderListDto billing : billingList){
                List<Map<String, Object>> feeList = new ArrayList<>();
                BigDecimal orderTotalFee = BigDecimal.ZERO;
                for(BillingOrderFeeDto billingOrder : orderFeeList){
                    if(billing.getOrderNo().equals(billingOrder.getOrderNo())&&billingOrder.getServiceName().equals(billing.getServiceName())){
                        orderTotalFee = orderTotalFee.add(billingOrder.getAmountDue());
                        Map<String, Object> map = new HashMap<>();
                        map.put(TYPE, billingOrder.getFeeTypeName());
                        map.put("supplierId",billing.getCustomerId());
                        BigDecimal orderFee = billingOrder.getAmountDue();
                        if(null != orderFee){
                            orderFee = orderFee.setScale(3, BigDecimal.ROUND_HALF_UP);
                        }
                        map.put("value", orderFee + "");
                        feeList.add(map);
                    }
                }
                    //每个订单的总计金额
                orderTotalFee = orderTotalFee.setScale(3, BigDecimal.ROUND_HALF_UP);
                billing.setAmountDue(orderTotalFee);
                //返回数据
                billing.setOrderFeeList(feeList);
                BillingOrderListStringDto billingOrderListStringDto = new BillingOrderListStringDto();
                BeanUtils.copyProperties(billing, billingOrderListStringDto);
                billingOrderListStringDto.setAmountDue(billing.getAmountDue().toString());
                billingListString.add(billingOrderListStringDto);
            }
        }
        return billingListString;
    }


    /**
     * 根据账单号获取账单下所有订单
     * @param params
     * @return
     */
    @Override
    public QResultDto getOrdersByBillNo(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        String type=pd.getString(TYPE);
        //根据条件获取账单列表
        List<BillingOrderListStringDto> billingList =new ArrayList<BillingOrderListStringDto>();
        if(TrdConstants.BillType.RECEIVALE.equals(type)){
            billingList = ordersByBillNo(pd, "findOrdersBySupplierFilterListPage");
        }
        else
        {
            billingList = ordersByBillNo(pd, "findOrdersByFilterListPage");
        }
        return new QResultDto(billingList, pd.getPagination());
    }

    /**
     * 根据账单号获取账单下所有订单-客户平台
     * @param q
     * @param billNo
     * @param orderNo
     * @param productUid
     * @param customerId
     * @param startEffectTime
     * @param endEffectTime
     * @param isSearch
     *@param pageIndex
     * @param pageSize
     * @param sort
     * @param asc     @return
     */
    @Override
    public QResultDto getOrdersByBillNoForCustomer(String q, String billNo, String orderNo, String productUid, Integer customerId, String startEffectTime, String endEffectTime, Boolean isSearch, int pageIndex, int pageSize, String sort, Boolean asc,String type){
        //是否主帐号
        boolean isPrimaryAccount = isPrimaryAccount(customerId);
        //查询参数组装
        q = StringUtils.replaceSqlPattern(q);
        QueryParams params = new QueryParams(pageSize, pageIndex, q, sort, asc);
        params.put("billNo", billNo);
        params.put("orderNo", orderNo);
        params.put("productUid", productUid);
        params.put("startEffectTime", billingService.populateTime(startEffectTime));
        params.put("endEffectTime", billingService.populateTime(endEffectTime));
        params.put("type", type);
        if(!isPrimaryAccount){
            params.put("customerId", customerId);
        }else{
            if(isSearch){
                params.put("customerId", customerId);
            }
            return getOrdersByBillNo(params);
        }

        ParamData pd = convertQueryParams(params);
        //根据条件获取账单列表
        List<BillingOrderListStringDto> billingList = ordersByBillNo(pd, "findOrdersByFilterListPageForCustomer");
        return new QResultDto(billingList, pd.getPagination());
    }
    /**
     * 子帐号订单费用总计
     * @param billNo
     * @param userId
     * @return
     */
    @Override
    public Map<String, Object> getOrderAmountSub(String billNo, Integer userId,String type){
        ParamData paramData = new ParamData();
        paramData.put("billNo", billNo);
        paramData.put("userId", userId);
        paramData.put("type", type);
        return (Map<String, Object>) dao.findForObject(getSqlName("getOrderAmountSub"), paramData);
    }

    /**
     * 是否主帐号
     * @param customerId
     * @return
     */
    private boolean isPrimaryAccount(Integer customerId) {
        CusUser user = customerUserService.findById(customerId);
        if(null != user && user.getIsSystem()){
            return true;
        }
        return false;
    }

    /**
     * 根据账单号删除
     * @param billNo
     */
    @Override
    public void deleteByBillNo(String billNo,String type,Integer supplier) {
        List<String> billNos = new ArrayList<>();
        billNos.add(billNo);
        deleteByBillNos(billNos,type,supplier);
    }

    /**
     * 删除账单下所有订单
     * @param billNos
     */
    @Override
    public void deleteByBillNos(List<String> billNos,String type,Integer supplier){
        //获取账单下所有订单
        List<String> orderNos = findOrderNosByBillNo(billNos,type);
        //修改订单为没有生成过账单状态
        ordServiceBillService.updateIsBilledStatus(orderNos, false,type,supplier);
    }
    /**
     * 删除账单下所有订单关联表
     * @param billNos
     */
    @Override
    public void deleteByBillNosOrderRe(List<String> billNos,String type){
        ParamData paramData = new ParamData();
        paramData.put("billNos", billNos);
        paramData.put("type", type);
        dao.delete(getSqlName("deleteByBillNos"), paramData);
    }
    /**
     * 根据任务编码删除账单订单关联
     * @param taskCodes
     * @param type
     *
     */
    @Override
    public void batchDeleteByTaskCodes(List<String> taskCodes,String type){
        //获取账单下所有订单
        List<String> orderNos = findOrderNosByTaskCodes(taskCodes,type);
        if(taskCodes!=null && taskCodes.size()>0){
            for(String taskCode:taskCodes){
                BillingTask billingTask=billingTaskService.findByTaskCode(taskCode,"");
                //修改订单为没有生成过账单状态
                ordServiceBillService.updateIsBilledStatus(orderNos, false,type, Integer.parseInt( billingTask.getCustomerId()));
            }
        }
        //修改订单为没有生成过账单状态
        ParamData paramData = new ParamData();
        if(taskCodes!=null && taskCodes.size()>0){
            paramData.put("taskCodes", taskCodes);
        }
        paramData.put("type", type);
        dao.delete(getSqlName("batchDeleteByTaskCodes"), paramData);
    }


    private List<String> findOrderNosByTaskCodes(List<String> taskCodes,String type) {
        ParamData paramData = new ParamData();
        if(taskCodes!=null && taskCodes.size()>0){
            paramData.put("taskCodes", taskCodes);
        }
        paramData.put("type", type);
        return dao.findForList(getSqlName("findOrderNosByTaskCodes"), paramData, String.class);
    }

    /**
     * 获取订单金额
     * @param billingList
     * @return
     */
    @Override
    public List<BillingOrderFeeDto> getOrderFee(List<BillingOrderListDto> billingList,String type){
        if(null != billingList){
            List<String> orderNos = new ArrayList<>();
            for(BillingOrderListDto billingOrderListDto: billingList){
                if(null != billingOrderListDto){
                    orderNos.add(billingOrderListDto.getOrderNo());
                }
            }
            if(orderNos.size() > 0){
                ParamData paramData = new ParamData();
                paramData.put("orderNos", orderNos);
                paramData.put("type", type);
                if(TrdConstants.BillType.RECEIVALE.equals(type)){
                    paramData.put("supplierId", billingList.get(0).getCustomerId());
                    return dao.findForList(getSqlName("getFeeByOrderNosForSupplier"), paramData, BillingOrderFeeDto.class);
                }
                return dao.findForList(getSqlName("getFeeByOrderNos"), paramData, BillingOrderFeeDto.class);
            }
        }
        return null;
    }

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.bill.entity.BillingOrderRelMapper";
    }
}
